package main

import (
	"fmt"
	"time"
)

func main() {
	//两个协程，一个写入，一个读取，共50笔数据
	//只有两个协程完成，主线程才退出
	//这里的问题是，如何让主线程知道完成任务了，再退出
	intChan := make(chan int, 50)
	noticeChan := make(chan bool, 1)
	go writeData(intChan)
	go readData(intChan, noticeChan)

	for {
		_, ok := <-noticeChan //由于使用了协程，所以这里不会死锁，而是阻塞，一旦管道被关闭，则ok为false
		if !ok {
			break
		}
	}
	fmt.Println("任务结束")
}

func writeData(intChan chan int) {
	defer close(intChan) //主动写入的协程进行管道的关闭,如果这里不关闭，主线程会在这个协程执行完之后死锁
	for i := 1; i <= 50; i++ {
		intChan <- i
		time.Sleep(100 * time.Millisecond)
	}
	fmt.Println("写入结束了")
}

//写法2：其实这样写就可以了。。。。
func readData2(intChan chan int, noticeChan chan bool) {
	defer close(noticeChan)
	for v := range intChan {
		fmt.Printf("%v \n", v)
		time.Sleep(200 * time.Millisecond)
	}
	fmt.Println("读取结束")
}

//写法1
func readData(intChan chan int, noticeChan chan bool) {
	defer close(noticeChan)
	for {
		//在使用协程的情况，管道被close，也就说明不会再放入数据，那么一旦读取完，ok就会为false
		//注意，在使用协程的情况，从管道读取数据，默认是阻塞的，所以不会死锁
		v, ok := <-intChan
		if !ok {
			break
		}
		fmt.Printf("%v \n", v)
	}
	fmt.Println("读取结束了")
	//一旦读取结束，就通知主线程
	noticeChan <- true

}
